﻿package com.bankcomm.luafuction;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.keplerproject.luajava.LuaException;
import org.keplerproject.luajava.LuaObject;
import org.keplerproject.luajava.LuaState;
import org.xml.sax.SAXException;

import android.content.Intent;

import com.bankcomm.common.ConfigManager;
import com.bankcomm.common.LPMid;
import com.bankcomm.ui.BaseViewCopy;
import com.bankcomm.ui.EMPView;
import com.bankcomm.util.BranchBankUtils;
import com.rytong.tools.crypto.AESCipher;
import com.rytong.tools.datastorage.PackageManagerAndroid;
import com.rytong.tools.httpconnect.HttpManager;
import com.rytong.tools.httpconnect.WaitDialog;
import com.rytong.tools.httpconnect.HttpManager.NoGatewayException;
import com.rytong.tools.ui.AtomParser;
import com.rytong.tools.ui.BaseView;
import com.rytong.tools.ui.Component;
import com.rytong.tools.ui.ComponentCopy;
import com.rytong.tools.ui.LPLayout;
import com.rytong.tools.ui.WaitProgressDialog;
import com.rytong.tools.utils.LPToastUtil;
import com.rytong.tools.utils.Utils;

public class LuaHTTP {
	
	private Hashtable<Object, Object> listenerHT_;

    public LuaHTTP() {
        try {
            Component.LUASTATE.pushObjectValue(this);
            Component.LUASTATE.setGlobal("luahttp");
            final String luahead = "http = {}; ";
            final String luafc1 = "function http:postAsyn(header, url, body, callback,parameters) local a1 = luahttp:postAsyn(header, url, body, callback,parameters); return a1; end;";
            final String luafc2 = "function http:postAsynWithoutDialog(header, url, body, callback,parameters) local a1 = luahttp:postAsynWithoutDialog(header, url, body, callback,parameters); return a1; end;";
            final String luafc3 = "function http:postSyn(header, url, body) local a1 = luahttp:postSyn(header, url, body); return a1; end;";
            final String luafc4 = "function http:setListener (request, listener) luahttp:setListener (request, listener); end;";
            final String luafc5 = "function http:abort(table) luahttp:abort(table); end;";
            final String luafc6="function http:submit(name) luahttp:submit(name); end;";
            Component.LUASTATE.gc(LuaState.LUA_GCCOLLECT, 0);
            Component.LUASTATE.LdoString(luahead.concat(luafc1).concat(luafc2).concat(luafc3)
            		.concat(luafc4).concat(luafc5).concat(luafc6));
        } catch (LuaException e) {
            // TODO Auto-generated catch block
            Utils.printException(e);
        }
    }

    /**
     * table：为Lua中Table类型，每一个元素值为http:postAsyn()方法返回的对象。
     * 
     * 
     * 允许模板人员对发起的网络请求在一定条件下做Cancel处理，但是如果当前的请求已经完成则忽略处理。
     * （这个方法只针对脚本发起的Lua请求，页面在跳转前应自动处理当前页面中由节点对象发起的网络请求，如：img属性src，防止异常发生）
     * 
     * @param table
     */
    public void abort(LuaObject table) {
        table.push();
        // 循环读取table中的属性值
        Component.LUASTATE.pushNil();
        String keyString = "";
        Object value = null;
        try {
            while (Component.LUASTATE.next(-2) != 0) {
                keyString = "";
                if (Component.LUASTATE.type(-2) == Component.LUASTATE.LUA_TNUMBER) {
                    keyString = Double.toString(Component.LUASTATE.toNumber(-2));
                } else if (Component.LUASTATE.type(-2) == Component.LUASTATE.LUA_TSTRING) {
                    keyString = Component.LUASTATE.toString(-2);
                }
                value = null;
                if (Component.LUASTATE.type(-1) == Component.LUASTATE.LUA_TNUMBER) {
                    value = Double.toString(Component.LUASTATE.toNumber(-1));
                } else if (Component.LUASTATE.type(-1) == Component.LUASTATE.LUA_TSTRING) {
                    value = Component.LUASTATE.toString(-1);
                } else if (Component.LUASTATE.type(-1) == Component.LUASTATE.LUA_TUSERDATA) {
                    value = Component.LUASTATE.toJavaObject(-1);
                }
                if (null != value && value instanceof HttpManager) {
                    HttpManager hm = (HttpManager) value;
                    hm.cancel();
                }
                Component.LUASTATE.pop(1);
            }
        } catch (Exception e) {
            Utils.printException(e);
        }
        Component.LUASTATE.pop(2);
    }

    /**
     * 交行模拟的同步请求，需要同一时刻只发一个请求。
     * @param header 头信息。
     * @param url 接口地址。
     * @param body 请求体。
     * @param callback 需要执行的回调函数。
     * @param parameters 回调函数需要的参数。
     * @return 一个HttpManager对象，暂时没有实际作用。
     */
    public Object postAsyn(final Object header, final Object url, final Object body, final Object callback,
            final LuaObject parameters) {
        //HttpManager hM = new HttpManager(ConfigManager.currentView_);
        final HttpManager hManager = LPMid.getInstance().hm_;
        if(Utils.SYN_REQUEST_NUMBER_ > 0){ // 已经有请求了。
        	return hManager;
        } else {
        	Utils.SYN_REQUEST_NUMBER_++;
        }
        
        String cityValue=""; //2级菜单调用Lua增加传递城市名称，支持最红电影票，城市联动
		String cityId = "";
        String saveCity = PackageManagerAndroid.ANDROIDDB.get("city_select");
        if(null != saveCity && !"".equalsIgnoreCase(saveCity)){
                String[] city =  saveCity.split("\\|");
                cityValue=city[1];
                cityId = city[0];
        }
		final String tempbody = "currentcity=" + Utils.escapeURIComponent(cityValue)
				+ "&currentcityId=" + cityId+"&"+(String)body;
		
		
        LPMid.getInstance().waitDialog_.addFgTask(ConfigManager.currentView_, null, 0, 0, 0, new WaitDialog.Task(0){
            String reply = "";
            final String urlTemp = Utils.checkUrl(url);

            @Override
            public void run(WaitDialog arg0) throws Exception {
                // TODO Auto-generated method stub
                LuaObject table = null;
                HashMap<String, String> hashMap = null;
                if (null != header) {
                    table = (LuaObject) header;
                    table.push();
                    // 循环读取table中的属性值
                    Component.LUASTATE.pushNil();
                    while (Component.LUASTATE.next(-2) != 0) {
                        hashMap.put(Component.LUASTATE.toString(-2), Component.LUASTATE.toString(-1));
                        Component.LUASTATE.pop(1);
                    }
                    Component.LUASTATE.pop(2);
                }

                String bodytemp = tempbody;
                if (null == bodytemp)
                    bodytemp = "";
                
                Utils.printOutToConsole("body-->"+bodytemp != null ? bodytemp:"");
                bodytemp = AESCipher.encrypt(bodytemp, AESCipher.clientKey_, AESCipher.clientIv_);
                if (null == hashMap)
                    reply = (String) hManager.sendPostRequest(ConfigManager.SERVER_URI.concat(urlTemp), bodytemp, this,
                            null, null);
                else
                    reply = (String) hManager.sendPostRequest(ConfigManager.SERVER_URI.concat(urlTemp), bodytemp, this,
                            null, null, hashMap);
                if (!HttpManager.isTimeout && !HttpManager.isAppUpgrading)
                    reply = AESCipher.decrypt(reply, AESCipher.serverKey_, AESCipher.serverIv_);
                if(LPToastUtil.getInstance().isBranchBank){
					reply = BranchBankUtils.addBrAtEnd(BranchBankUtils.includeAloneAttribute(reply));
				}
            }

            public void onSuccess(WaitDialog dlg) {
                try {
//                	if(HttpManager.isTimeout || HttpManager.isAppUpgrading){
//                		if (HttpManager.isTimeout) {
//                		    HttpManager.isTimeout = false;
//                		    reply = Utils.getStringFormAsset(ConfigManager.currentView_, "timeout.xml");
//                		} else if(HttpManager.isAppUpgrading){
//                			 HttpManager.isAppUpgrading = false;
//                			 reply = Utils.getStringFormAsset(ConfigManager.currentView_, "app-upgrading.xml");
//                		}
//                		final AtomParser apc = new AtomParser(ConfigManager.currentView_, AtomParser.ENTIRE);
//                		reply = Utils.unescapeHTML(reply);
//                		reply = Utils.insteadOfSpecillCharacter(reply, true);
//                		android.util.Xml.parse(reply, apc);
//                		ConfigManager.currentView_.runOnUiThread(new Runnable() {
//                            public void run() {
//                                // TODO Auto-generated method stub
//                                ConfigManager.currentView_.setContentView(ComponentCopy.COMPONENT.getLPView());
//                            }
//
//                        });
//                    } else {
                        donCallback("true", hManager, reply, callback, parameters);
//                    }
                } catch (LuaException e) {
                    // TODO Auto-generated catch block
                	Utils.SYN_REQUEST_NUMBER_ = 0;
                    Utils.printException(e);
                } 
                super.onSuccess(dlg);
            }

            public void onFailure(WaitDialog dlg) {
                super.onFailure(dlg);
                if(null != getErrMsg() && !getErrMsg().equalsIgnoreCase("CDATA")){
                	Utils.SYN_REQUEST_NUMBER_ = 0;
                	((BaseViewCopy) ConfigManager.currentView_).handleException(getErrMsg());
                	return;
                }
                try {
                    donCallback("false", hManager, reply, callback, parameters);
                } catch (LuaException e) {
                    // TODO Auto-generated catch block
                	Utils.SYN_REQUEST_NUMBER_ = 0;
                    Utils.printException(e);
                }

              
//                if (err.contains("CDATA")) {
//                    // 表示服务端传过来的为错误信息,代替以前的error错误信息节点
//                    String temp = err.substring(err.indexOf("[CDATA[") + 7, err.indexOf("]]></script>")).trim();
//                    Component.LUASTATE.LdoString(temp);
//                } else {
//                    EMPView.mid_.alert(ConfigManager.currentView_, err, false);
//                }
                
            }
        });

        return hManager;

    }
    
    /**
     * 交行模拟的异步请求，同一时刻可以发送多个请求，因此不设置dialog，不限制用户的点击次数。
     * @param header 头信息。
     * @param url 接口地址。
     * @param body 请求的body部分。
     * @param callback 请求成功之后需要执行的回调函数。
     * @param parameters 回调函数需要的参数列表。
     * @return 一个HttpManager对象，暂时没有实际作用。
     */
    public Object postAsynWithoutDialog(final Object header, final Object url, final Object body, final Object callback,
            final LuaObject parameters) {
        final HttpManager hManager = LPMid.getInstance().hm_;
        LPMid.getInstance().waitDialog_.addBgTask(new WaitDialog.Task(0){ // 异步请求取消对话框。
            String reply = "";
            final String urlTemp = Utils.checkUrl(url);

            @Override
            public void run(WaitDialog arg0) throws Exception {
                // TODO Auto-generated method stub
                LuaObject table = null;
                HashMap<String, String> hashMap = null;
                if (null != header) {
                    table = (LuaObject) header;
                    table.push();
                    // 循环读取table中的属性值
                    Component.LUASTATE.pushNil();
                    while (Component.LUASTATE.next(-2) != 0) {
                        hashMap.put(Component.LUASTATE.toString(-2), Component.LUASTATE.toString(-1));
                        Component.LUASTATE.pop(1);
                    }
                    Component.LUASTATE.pop(2);
                }

                String bodytemp = (String) body;
                if (null == bodytemp)
                    bodytemp = "";
                
                Utils.printOutToConsole("body-->"+bodytemp != null ? bodytemp:"");
                bodytemp = AESCipher.encrypt(bodytemp, AESCipher.clientKey_, AESCipher.clientIv_);
                if (null == hashMap)
                    reply = (String) hManager.sendPostRequest(ConfigManager.SERVER_URI.concat(urlTemp), bodytemp, this,
                            null, null);
                else
                    reply = (String) hManager.sendPostRequest(ConfigManager.SERVER_URI.concat(urlTemp), bodytemp, this,
                            null, null, hashMap);
                if (!HttpManager.isTimeout && !HttpManager.isAppUpgrading)
                    reply = AESCipher.decrypt(reply, AESCipher.serverKey_, AESCipher.serverIv_);
                if(LPToastUtil.getInstance().isBranchBank){
					reply = BranchBankUtils.addBrAtEnd(BranchBankUtils.includeAloneAttribute(reply));
				}
            }

            public void onSuccess(WaitDialog dlg) {
                try {
//                	if(HttpManager.isTimeout || HttpManager.isAppUpgrading){
//                		if (HttpManager.isTimeout) {
//                		    HttpManager.isTimeout = false;
//                		    reply = Utils.getStringFormAsset(ConfigManager.currentView_, "timeout.xml");
//                		} else if(HttpManager.isAppUpgrading){
//                			 HttpManager.isAppUpgrading = false;
//                			 reply = Utils.getStringFormAsset(ConfigManager.currentView_, "app-upgrading.xml");
//                		}
//                		final AtomParser apc = new AtomParser(ConfigManager.currentView_, AtomParser.ENTIRE);
//                		reply = Utils.unescapeHTML(reply);
//                		reply = Utils.insteadOfSpecillCharacter(reply, true);
//                		android.util.Xml.parse(reply, apc);
//                		ConfigManager.currentView_.runOnUiThread(new Runnable() {
//                            public void run() {
//                                // TODO Auto-generated method stub
//                                ConfigManager.currentView_.setContentView(ComponentCopy.COMPONENT.getLPView());
//                            }
//
//                        });
//                    } else {
                        donCallback("true", hManager, reply, callback, parameters);
//                    }
                } catch (LuaException e) {
                    // TODO Auto-generated catch block
                    Utils.printException(e);
                } 
                super.onSuccess(dlg);
            }

            public void onFailure(WaitDialog dlg) {
                super.onFailure(dlg);
                if(null != getErrMsg() && !getErrMsg().equalsIgnoreCase("CDATA")){
                	((BaseViewCopy) ConfigManager.currentView_).handleException(getErrMsg());
                	return;
                }
                try {
                    donCallback("false", hManager, reply, callback, parameters);
                } catch (LuaException e) {
                    // TODO Auto-generated catch block
                    Utils.printException(e);
                }

              
//                if (err.contains("CDATA")) {
//                    // 表示服务端传过来的为错误信息,代替以前的error错误信息节点
//                    String temp = err.substring(err.indexOf("[CDATA[") + 7, err.indexOf("]]></script>")).trim();
//                    Component.LUASTATE.LdoString(temp);
//                } else {
//                    EMPView.mid_.alert(ConfigManager.currentView_, err, false);
//                }
                
            }
        });

        return hManager;

    }

    private void donCallback(String b, HttpManager hManager, String reply, Object callback, LuaObject parameters)
            throws LuaException {
    	 boolean isReachable = false;
    	 int progress = 0;
    	//listener, 当前仅支持结束状态（换网络后再支持中间状态）
    	if (b.equals("true")) {
    		isReachable = true;
    		progress = 100;
    		listenerAction(hManager, progress, hManager.responseCode_, isReachable);
    	} else {
    		isReachable = false;
    		progress = 0;
    		listenerAction(hManager, progress, hManager.responseCode_, isReachable);
    	}
        // TODO Auto-generated method stub

        // 创建一个table
        Component.LUASTATE.newTable();
        LuaObject tableTemp = Component.LUASTATE.getLuaObject(-1);
        Component.LUASTATE.pop(1);
        // 将约定的固有参数压入表中
        tableTemp.push();

        Map<String, List<String>> map = hManager.hc_.getHeaderFields();
        Set<String> set = map.keySet();
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
        	String key = iterator.next();
            String value = null;
            if (key != null) {
            	value = hManager.hc_.getHeaderField(key);
            }
            if(key != null && value != null){
            	Component.LUASTATE.pushObjectValue(key);
                Component.LUASTATE.pushObjectValue(value);
                Component.LUASTATE.setTable(-3);
            }
        }
        Component.LUASTATE.pop(1);
        
        // 创建一个table
        LuaObject table = null;
        if (parameters != null && parameters.isTable()) {
            parameters.push();
        } else {
            Component.LUASTATE.newTable();
            table = Component.LUASTATE.getLuaObject(-1);
            Component.LUASTATE.pop(1);
            // 将约定的固有参数压入表中
            table.push();
        }

        Component.LUASTATE.pushObjectValue("responseBody");
        Component.LUASTATE.pushObjectValue(reply);
        Component.LUASTATE.setTable(-3);
        Component.LUASTATE.pushObjectValue("isReachable");
        Component.LUASTATE.pushBoolean(isReachable);
        Component.LUASTATE.setTable(-3);
        Component.LUASTATE.pushObjectValue("responseCode");
        Component.LUASTATE.pushObjectValue(hManager.responseCode_);
        Component.LUASTATE.setTable(-3);
        Component.LUASTATE.pushObjectValue("progress");
        Component.LUASTATE.pushObjectValue(progress);
        Component.LUASTATE.setTable(-3);
        Component.LUASTATE.pushObjectValue("responseHeader");
        Component.LUASTATE.pushObjectValue(tableTemp);
        Component.LUASTATE.setTable(-3);
        Component.LUASTATE.pop(1);

        if (null != reply) {
            Utils.printOutToConsole(reply);
            // 如果存在返回值,则调用Lua脚本中的callback方法,且,将reply作为一个参数传递给该方法
            if(callback != null && callback instanceof LuaObject){ // 如果给定的回调函数确实存在，那么就执行对应的Lua方法。
            	if (parameters != null && parameters.isTable())
            		setParamsToLuaFuction((LuaObject) callback, parameters);
            	else
            		setParamsToLuaFuction((LuaObject) callback, table);
            }
        }
    }

    public Object postSyn(final Object header, final Object url, final Object body) {
        String reply = null;
        LuaObject table = null;
        try {
        	// 以下过程发请求。
            String urlTempString = Utils.checkUrl(url);
            String bodytemp = (String) body;
            // 请求参数需要加密时候打开
            bodytemp = AESCipher.encrypt((String) body, AESCipher.clientKey_, AESCipher.clientIv_);
            reply = (String) LPMid.getInstance().hm_.sendPostRequest(ConfigManager.SERVER_URI.concat(urlTempString),
                    bodytemp, null, null, null);
            // 解密时候打开
            // 单元测试不走解密
            reply = AESCipher.decrypt(reply, AESCipher.serverKey_, AESCipher.serverIv_);

            if(LPToastUtil.getInstance().isBranchBank){
				reply = BranchBankUtils.addBrAtEnd(BranchBankUtils.includeAloneAttribute(reply));
			}
            // 创建一个table
            Component.LUASTATE.newTable();
            table = Component.LUASTATE.getLuaObject(-1);
            Component.LUASTATE.pop(1);
            // 将约定的固有参数压入表中
            table.push();

            Component.LUASTATE.pushObjectValue("responseBody");

            Component.LUASTATE.pushObjectValue(reply);
            Component.LUASTATE.setTable(-3);
            Component.LUASTATE.pop(1);
            Utils.printOutToConsole(reply);
        } catch (Exception e) {
            // TODO Auto-generated catch block
        	// 处理异常。
        	((BaseViewCopy) ConfigManager.currentView_).handleException(e.getMessage());
        }

        // String reply = url.toString();
        // if (reply.indexOf("/") != -1) {
        // reply = reply.substring(reply.indexOf("/") + 1);
        // }
        // String reply = Utils.getStringFormAsset(ConfigManager.currentView_, stringUrl);
        return reply;
        // 需要加解密的时候返回table
        // return table;
    }
    
    /**
     * 
     * @param callback
     *            需要执行的lua脚本方法
     * @param reply
     *            需要传递的参数，一般为联网后获取的服务端报文
     */
    protected void setParamsToLuaFuction(LuaObject callback, Object table) {
        // TODO Auto-generated method stub
        if (callback.isFunction()) {
            // 如果是lua则将参数代入并执行并执行
            try {
                callback.call(new Object[] { table }, 0);
            } catch (LuaException e) {
                // TODO Auto-generated catch block
                Utils.printException(e);
            }
        }
    }

    public void setListener(Object request, Object listener) {
    	if (listenerHT_ == null) {
    		listenerHT_ = new Hashtable<Object, Object>();
    	}
    	listenerHT_.put(request, listener);
    }
    	
    public void listenerAction(Object request, Object progress, Object responseCode, Boolean isReachable) {
    	if (listenerHT_ == null) {
    		return;
    	}
        Object listener = listenerHT_.get(request);
        LuaObject luaObject = null;
        if (listener instanceof LuaObject)
            luaObject = (LuaObject) listener;
        if (luaObject == null) {
        	return;
        }
        
        // 创建一个table
        Component.LUASTATE.newTable();
        LuaObject table = Component.LUASTATE.getLuaObject(-1);
        Component.LUASTATE.pop(1);
        // 将约定的固有参数压入表中
        table.push();
        try {
            Component.LUASTATE.pushObjectValue("isReachable");
            Component.LUASTATE.pushBoolean(isReachable);
            Component.LUASTATE.setTable(-3);
            Component.LUASTATE.pushObjectValue("responseCode");
            Component.LUASTATE.pushObjectValue(responseCode);
            Component.LUASTATE.setTable(-3);
            Component.LUASTATE.pushObjectValue("progress");
            Component.LUASTATE.pushObjectValue(progress);
            Component.LUASTATE.setTable(-3);
            Component.LUASTATE.pop(1);
            luaObject.call(new Object[] { table });
        } catch (LuaException e) {
            Utils.printException(e);
        }
    }
    
    public void submit(Object comp){
    	if(ConfigManager.currentView_ instanceof EMPView)
    	((EMPView)ConfigManager.currentView_).sendForm((LPLayout)comp);
    }
}
